package steed.hadmin.action;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.JoinColumn;
import javax.persistence.Transient;

import java.util.Set;

import steed.action.admin.BaseAdminAction;
import steed.action.intercepter.BeforAction;
import steed.domain.application.DWZMessage;
import steed.domain.system.AdminUser;
import steed.ext.domain.information.Information;
import steed.hadmin.annotation.TableHeader;
import steed.hibernatemaster.domain.BaseDatabaseDomain;
import steed.hibernatemaster.domain.BaseDomain;
import steed.hibernatemaster.domain.BaseRelationalDatabaseDomain;
import steed.hibernatemaster.domain.BaseUnionKeyDomain;
import steed.hibernatemaster.domain.Page;
import steed.hibernatemaster.util.DaoUtil;
import steed.util.base.BaseUtil;
import steed.util.base.DomainUtil;
import steed.util.base.StringUtil;
import steed.util.digest.Md5Util;
import steed.util.reflect.ReflectResult;
import steed.util.reflect.ReflectUtil;

/**
 * H+后台管理前端页面专用action
 * @author 战马
 *
 * @email battle_steed@163.com
 */
public abstract class HadminAction<SteedDomain extends BaseDatabaseDomain> extends BaseAdminAction<SteedDomain> implements BeforAction{
	private static final long serialVersionUID = -4802757961575616721L;
	/**
	 * 排序字段
	 */
	protected String sort;
	/**
	 * 升序还是降序
	 */
	protected boolean isDesc;
	
	protected String[] ids;
	
	public void setIds(String ids) {
		this.ids = ids.split(",");
	}
	public String getSort() {
		return sort;
	}
	public void setSort(String sort) {
		sort = sort.replace("__", ".");
		this.sort = sort;
	}
	public boolean getIsDesc() {
		return isDesc;
	}
	
	@Override
	public AdminUser getLoginUser() {
		return (AdminUser) super.getLoginUser();
	}
	public void setOrder(String order) {
		if (!StringUtil.isStringEmpty(order)) {
			isDesc = "desc".equalsIgnoreCase(order);
		}
	}
	
	@Override
	protected DWZMessage afterUpdate() {
		DWZMessage dwzMessage = new DWZMessage(DWZMessage.type_update, DaoUtil.managTransaction());
		return dwzMessage;
	}
	
	@Override
	protected DWZMessage afterSave() {
		DWZMessage dwzMessage = new DWZMessage(DWZMessage.type_save, DaoUtil.managTransaction());
		return dwzMessage;
	}
	@Override
	protected DWZMessage afterDelete() {
		throw new RuntimeException("请重写steed.hadmin.action.HadminAction.afterDelete(int)方法!steed.hadmin.action.HadminAction.afterDelete()作废");
	}
	
	/**
	 * 
	 * @param deletedRows 删除的数据行数,-1表示删除失败
	 * @return 给前端返回的消息
	 */
	protected DWZMessage afterDelete(int deletedRows) {
		if (!DaoUtil.managTransaction() || deletedRows == -1) {
			return new DWZMessage(500, "该记录关联有其它数据,请先删除关联的数据再删除该记录!","删除失败");
		}else {
			return new DWZMessage(0, "成功删除"+deletedRows+"条数据", "删除成功");
		}
	}
	
	@Override
	public String delete() {
		writeObjectMessage(afterDelete(DaoUtil.smartDeleteByIds((Class<? extends BaseRelationalDatabaseDomain>) getModel().getClass(), ids)));
//		writeObjectMessage(new_key_return container=);
		return null;
	}
	private int offset;
	
	public void setOffset(int offset) {
		this.offset = offset;
		countCurrentPage();
	}
	
	private void countCurrentPage() {
		currentPage = offset/pageSize+1;
	}
	
	public void setLimit(int limit) {
		pageSize = limit;
		countCurrentPage();
	}
	
	protected class Table{
		public Table() {
		}
		public long total;
		public Collection<?> rows;
	}
	

	protected Collection<Object> dealCollection(Collection<?> c){
		List<Object> list = new ArrayList<>();
		for (Object temp:c) {
			Object putField2Map = putField2Map(temp);
			if (putField2Map instanceof Map) {
				Map<String, Object> foo = new HashMap<>();
				Map<String, Object> map = (Map<String, Object>) putField2Map;
				for(Entry<String, Object>  e:map.entrySet()){
					foo.put(e.getKey().replace(".", "__"), e.getValue());
				}
				
				list.add(foo);
			}else{
				list.add(putField2Map);
			}
		}
		return list;
	}
	
	protected Object putField2Map(Object object){
		if (object == null) {
			return null;
		}
		if (object instanceof BaseDomain) {
			return DomainUtil.putField2Map(object);
		}else if (object instanceof Map) {
			Map<String,Object> container = new HashMap<>();
			Map<String,Object> temp = (Map) object;
			Set<Entry<String, Object>> entrySet = temp.entrySet();
			for(Entry<String, Object> e:entrySet){
				Object value = e.getValue();
				if (value != null) {
					if (value instanceof BaseDomain) {
						DomainUtil.putField2Map(value, container, e.getKey()+".");
					}else {
						container.put(e.getKey(), value);
					}
				}
			}
			return container;
		}
		return object;
	}
	
	
	public void query(List<String> desc, List<String> asc){
		query(desc, asc, null);
	}
	
	
	/**
	 * 处理分页数据,可以在该方法往分页数据里面添加自己的数据,更改或移除分页数据
	 * @param pageData 前端分页展示的数据
	 */
	protected void dealPageData(Collection<?> pageData){
		int index = 0;
		for(Object temp:pageData) {
			dealRowData(temp,index++);
		}
	}
	/**
	 * 处理分页数据的某一行,若当前分页有100条数据,则该方法会被调用100次
	 * @param rowData 行数据
	 * @param rowNumber 行号 从0开始
	 */
	protected void dealRowData(Object rowData,int rowNumber){
		
	}
	
	public void query(List<String> desc, List<String> asc,String[] groupBy){
		DomainUtil.fuzzyQueryInitialize(getModel(),false);
		String[] listFields = getListFields();
		if (listFields == null) {
			BaseUtil.getLogger().warn("getListFields返回null会查询实体类级其关联的所有数据,影响性能,建议该方法只返回要用到的字段!!!!");
		}
		if (isServerPagination()) {
			Page<Object> listCustomField = DaoUtil.listCustomField(getModel().getClass(), pageSize, currentPage, getModelQueryMapByRequestParam(), desc, asc, !isPaginationLoop(), groupBy, listFields);
			Table table = page2BootstrapTable(listCustomField);
			writeObjectMessage(table);
		}else {
			List<Object> listAllCustomField = DaoUtil.listAllCustomField(getModel().getClass(), getModelQueryMapByRequestParam(), desc, asc, groupBy, listFields);
			dealPageData(listAllCustomField);
			
			writeObjectMessage(dealCollection(listAllCustomField));
		}
	}
	protected Table page2BootstrapTable(Page<Object> listCustomField) {
		dealPageData(listCustomField.getDomainCollection());
		
		
		Table table = new Table();
		table.total = listCustomField.getRecordCount();
		
		table.rows = dealCollection(listCustomField.getDomainCollection());
		return table;
	}
	
	public void query() {
		query(null);
	}
	public void query(String[] groupBy) {
		if (!StringUtil.isStringEmpty(sort)) {
			if (isDesc) {
				query(Arrays.asList(sort),null,groupBy);
			}else {
				query(null,Arrays.asList(sort),groupBy);
			}
		}else{
			query(null,null,groupBy);
		}
	}
	/**
	 * 返回你想查询实体类的字段
	 * @return 你要在index表格显示的字段
	 */
	protected abstract String[] getListFields();
	
	protected String[] getListFieldNames() {
		String[] listFields = getListFields();
		if (listFields == null) {
			return null;
		}
		Class<? extends BaseDatabaseDomain> class1 = getModel().getClass();
		String[] listFieldNames = new String[listFields.length];
		for(int i = 0; i < listFields.length;i++){
			ReflectResult result = ReflectUtil.getChainField(class1, listFields[i]);
			if (result == null) {
				listFieldNames[i] = listFields[i];
			}
			TableHeader note = ReflectUtil.getAnnotation(TableHeader.class, result.getTarget(), result.getField());
			if (note != null) {
				listFieldNames[i] = note.value();
			}else {
				listFieldNames[i] = listFields[i];
			}
		}
		return listFieldNames;
	}
	
	private PageConfig getPageConfig(){
		PageConfig pageConfig;
		if ((pageConfig = (HadminAction<SteedDomain>.PageConfig) getRequestAttribute("pageConfig")) == null) {
			pageConfig = new PageConfig(); 
			setRequestAttribute("pageConfig", pageConfig);
		}
		
		if (isServerPagination()) {
			pageConfig.sidePagination = "server";
		}else {
			pageConfig.sidePagination = "client";
		}
		pageConfig.paginationLoop = isPaginationLoop();
		pageConfig.toolbar = getActionId();
		return pageConfig;
	}
	
	/**
	 * 获取列表页表格头部
	 * @return
	 */
	protected Map<String, String> getTableHeader(){
		Map<String, String> header = new LinkedHashMap<>();
		String[] listFields = getListFields();
		if (listFields != null) {
			String[] listFieldNames = getListFieldNames();
			for (int i = 0; i < listFields.length; i++) {
				header.put(listFields[i].replace(".", "__"), listFieldNames[i]);
			}
		}
		return header;
	}
	
	
	
	/**
	 * 获取该action的id(主要用于前端控件的id分配)
	 * @return
	 */
	protected String getActionId() {
		String actionId = getRequestParameter("actionId") ;
		return StringUtil.isStringEmpty(actionId)?Md5Util.Md5Digest(getClass().getName().replace(".", "__")):actionId;
	}
	
	/**
	 * 是否服务端分页
	 * @return
	 */
	protected boolean isServerPagination() {
		return true;
	}
	/**
	 * 是否循环/无限分页
	 * @return
	 */
	protected boolean isPaginationLoop() {
		return false;
	}
	
	/**
	 * 获取表格数据的url
	 * @return
	 */
	protected String getQueryUrl() {
		return "query.act";
	}
	
	@Override
	public String index(List<String> desc, List<String> asc) {
		getPageConfig();
		//setRequestAttribute("tableHeader", getTableHeader());
		return steed_forward;
	}
	
	
	@Override
	public String index() {
		return index(null,null);
	}

	@Override
	public void doBeforAction() {
		setRequestAttribute("actionID", getActionId());
	}

	public class PageConfig{
//		protected boolean search = true;
//		protected boolean pagination = true;
//		protected boolean showRefresh = true;
//		protected boolean showToggle = true;
//		protected boolean showColumns = true;
		/**
		 * 工具栏的ID
		 */
		private String toolbar;
		private String sidePagination = "server";
//		private String sidePagination = "client";
		
		private boolean paginationLoop = false;
		public String getToolbar() {
			return toolbar;
		}
		public void setToolbar(String toolbar) {
			this.toolbar = toolbar;
		}
		public String getSidePagination() {
			return sidePagination;
		}
		public void setSidePagination(String sidePagination) {
			this.sidePagination = sidePagination;
		}
		public boolean isPaginationLoop() {
			return paginationLoop;
		}
		public void setPaginationLoop(boolean paginationLoop) {
			this.paginationLoop = paginationLoop;
		}
		
	}
	
}
